package net;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 聊天(Chat)室服务端
 */

public class ThreadChatSever { //ThreadChatSever.class
    //定义服务端的ServerSocket属性
    private ServerSocket serverSocket;
    //构建一个集合对象，存储所有客户端的输出流对象
    private List<PrintWriter> allOut = new ArrayList<>();
    private static final int PORT;
    static {
        PORT = 8088; //可以从配置文件读取
    }
    public ThreadChatSever() {
        try {
            System.out.println("服务器开始启动");
            serverSocket = new ServerSocket(PORT);
            System.out.println("服务器启动OK，正在"+PORT+"端口上进行监听");
        }catch (Exception e){
            e.printStackTrace(); //让运维人员知道哪里出错了（后续这些信息记录到日志文件）
            System.out.println("服务器启动失败");
            System.exit(-1);
        }
    }
    /**
     * 线程任务类型
     */
    private class ClientHandler implements Runnable {
        private Socket socket;
        private String host;
        public ClientHandler(Socket socket) {
            this.socket = socket;
            //获取客户端地址信息
            host = socket.getInetAddress().getHostAddress();
        }

        public void run(){
            PrintWriter pw = null;
            try{
                //1.构建输入流对象(字符缓冲输入流)
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(
                                socket.getInputStream(), StandardCharsets.UTF_8));
                //2.构建输出流对象(字符缓冲输出流)
                pw = new PrintWriter(
                        new BufferedWriter(
                                new OutputStreamWriter(socket.getOutputStream(),
                                        StandardCharsets.UTF_8)),true);
                //将每个线程的输出流对象加入到集合中
                synchronized (allOut) {
                    allOut.add(pw);
                }
                //3.通过此对象读取写数据
                String data = null;
                while ((data = br.readLine()) != null) {
                    System.out.println(host +" say:" + data);
                    //写数据给客户端(后续是要在这里，把一个客户端的数据转发给所有客户端)
                    for(PrintWriter out:allOut) {
                        out.println(host + " say:" + data);
                    }
                }
            }catch (IOException e){
                e.printStackTrace();
            }finally {
                try{
                    //关闭资源
                    socket.close();
                    synchronized (allOut) {
                        allOut.remove(pw);
                    }
                    System.out.println("客户端退出");
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }
    }

    //启动服务读取数据
    public void start(){
        while (true) {
            try {
                //1.接收客户端的连接（主线程-接线员）
                Socket socket = serverSocket.accept();
                System.out.println("客户端连接成功");
                //2.启动线程处理客户端请求（读取请求中数据）
                new Thread(new ClientHandler(socket)).start();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) {
        new ThreadChatSever().start();
    }
}

